﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Assist;
using YJKDataLookAfter;
using Microsoft.Win32;

namespace YJKDataBase
{
	public abstract class RelationDatabase : Database, IDatabase
	{
		public string Name
		{
			get
			{
				return this.mName;
			}
		}

		public static string GetDefLibPath()
		{
			string location = Assembly.GetExecutingAssembly().Location;
			int length = location.LastIndexOf("\\");
			string text = location.Substring(0, length);
			int length2 = text.LastIndexOf("\\");
			return text.Substring(0, length2) + "\\FamilyLib";
		}

		public static string GetRegistData(string revitVer)
		{
			string text = "";
			string result;
			try
			{
				RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE", false).OpenSubKey("Hongye", false).OpenSubKey("HYFamilyLib", false);
				double num = 1.0;
				string name = "1.0";
				foreach (string text2 in registryKey.GetSubKeyNames())
				{
					if (Convert.ToDouble(text2) > num)
					{
						num = Convert.ToDouble(text2);
						name = text2;
					}
				}
				text = registryKey.OpenSubKey(name, false).OpenSubKey(revitVer, false).GetValue("Location").ToString() + "FamilyLib";
				result = text;
			}
			catch
			{
				result = text;
			}
			return result;
		}

		public static string GetIniData(string revitVer)
		{
			string text = "";
			string result;
			try
			{
				result = PathIni.ReadPath(revitVer);
			}
			catch
			{
				result = text;
			}
			return result;
		}

		public static string GetDefFamilyLibPath()
		{
			string location = Assembly.GetExecutingAssembly().Location;
			int length = location.LastIndexOf("\\");
			string text = location.Substring(0, length);
			int length2 = text.LastIndexOf("\\");
			return text.Substring(0, length2) + "\\FamilyLib";
		}

		public static SqliteDatabase GetSqliteDB(string fileName, string ver)
		{
			string text = RelationDatabase.GetIniData(ver);
			if (text == "")
			{
				text = RelationDatabase.GetDefFamilyLibPath();
				if (text == "")
				{
					throw new Exception(text + "\n没有检测到本地族库，请安装族库。");
				}
			}
			FileInfo fileInfo = new FileInfo(text + "\\" + fileName);
			if (fileInfo.Exists)
			{
				return new SqliteDatabase(fileInfo.FullName);
			}
			throw new Exception("没有检测到本地族库，请安装族库。");
		}

		public static RelationDatabase GetSqlServerDb(string configFileName, string dbName)
		{
			string fileName = AssistFunc.GetAppRootPath() + "\\Data\\Config.xml";
			string dataFromConfigFile = XmlUtils.GetDataFromConfigFile(fileName, "Server", "value");
			string dataFromConfigFile2 = XmlUtils.GetDataFromConfigFile(fileName, "Uid", "value");
			string dataFromConfigFile3 = XmlUtils.GetDataFromConfigFile(fileName, "Pwd", "value");
			return RelationDatabase.GetSqlServerDb(new ConnectData(dataFromConfigFile, dataFromConfigFile2, dataFromConfigFile3), dbName);
		}

		public static SqlServerDatabase GetSqlServerDb(ConnectData cd, string dbName)
		{
			return new SqlServerDatabase(dbName, cd);
		}

		public static RelationDatabase GetMySqlDb(string configFileName, string dbName)
		{
			string fileName = AssistFunc.GetAppRootPath() + "\\Data\\Config.xml";
			string dataFromConfigFile = XmlUtils.GetDataFromConfigFile(fileName, "Server", "value");
			string dataFromConfigFile2 = XmlUtils.GetDataFromConfigFile(fileName, "Uid", "value");
			string dataFromConfigFile3 = XmlUtils.GetDataFromConfigFile(fileName, "Pwd", "value");
			return RelationDatabase.GetMySqlDb(new ConnectData(dataFromConfigFile, dataFromConfigFile2, dataFromConfigFile3), dbName);
		}

		public static MySqlDatabase GetMySqlDb(ConnectData cd, string dbName)
		{
			return new MySqlDatabase(dbName, cd);
		}

		public abstract ISubjectTable SubjectTable { get; }

		public abstract ICategoryTable CategoryTable { get; }

		public abstract IObjectTable ObjectTable { get; }

		public abstract IObjectFileTable ObjectFileTable { get; }

		public bool Export(string fileName)
		{
			bool result;
			try
			{
				byte[] pReadByte = Resource1.ResourceManager.GetObject("BaseDb") as byte[];
				if (!new FileInfo(fileName).Exists)
				{
					RelationDatabase.WriteFile(pReadByte, fileName);
				}
				SqliteDatabase sqliteDatabase = new SqliteDatabase(fileName);
				DlgCompare dlgCompare = new DlgCompare(sqliteDatabase, this);
				if (dlgCompare.ShowDialog() == DialogResult.OK)
				{
					if (sqliteDatabase.Import(this, dlgCompare.CategoryList))
					{
						result = true;
					}
					else
					{
						sqliteDatabase.Dispose();
						new FileInfo(fileName).Delete();
						result = false;
					}
				}
				else
				{
					sqliteDatabase.Dispose();
					new FileInfo(fileName).Delete();
					MessageBox.Show("导出被取消。");
					result = false;
				}
			}
			catch
			{
				result = false;
			}
			return result;
		}

		public static bool WriteFile(byte[] pReadByte, string fileName)
		{
			FileStream fileStream = null;
			try
			{
				fileStream = new FileStream(fileName, FileMode.OpenOrCreate);
				fileStream.Write(pReadByte, 0, pReadByte.Length);
			}
			catch
			{
				return false;
			}
			finally
			{
				if (fileStream != null)
				{
					fileStream.Close();
				}
			}
			return true;
		}

		public bool Import(RelationDatabase newDB, List<CategoryForAdd> categoryList)
		{
			List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
			foreach (CategoryForAdd categoryForAdd in categoryList)
			{
				KeyValuePair<int, string> item = new KeyValuePair<int, string>(categoryForAdd.FamilyList.Count, categoryForAdd.Category.Name);
				list.Add(item);
			}
			MyProgressBar myProgressBar = new MyProgressBar(list, "导入导出族库", true);
			bool result;
			try
			{
				foreach (CategoryForAdd categoryForAdd2 in categoryList)
				{
					try
					{
						this.CategoryTable.Add(categoryForAdd2.Category);
					}
					catch (Exception)
					{
					}
					foreach (ObjectForAdd objectForAdd in categoryForAdd2.FamilyList)
					{
						if (objectForAdd.Add)
						{
							try
							{
								DbObject dbObject = this.ObjectTable[objectForAdd.dbObject.Name];
								if (dbObject != null)
								{
									DbObject dbObject2 = this.ObjectTable[objectForAdd.dbObject.Guid];
									if (dbObject2 != null && dbObject.Equals(dbObject2) && dbObject.Date < objectForAdd.dbObject.Date)
									{
										RelationDatabase.UpdateFamilyFile(newDB, this, objectForAdd.dbObject, "rvt");
									}
									else if (dbObject2 == null)
									{
										RelationDatabase.DownloadFamily(newDB, this, objectForAdd.dbObject, "rvt");
									}
								}
								else
								{
									DbObject dbObject3 = this.ObjectTable[objectForAdd.dbObject.Guid];
									if (dbObject3 != null)
									{
										if (MessageBox.Show(string.Concat(new object[]
										{
											"族",
											dbObject3.Name,
											"在新导入的族库中名字被更改为：",
											objectForAdd,
											"。是否继续使用原族库中的族名？"
										}), "鸿业族库", MessageBoxButtons.YesNo) != DialogResult.Yes)
										{
											dbObject3.Rename(objectForAdd.dbObject.Name);
										}
									}
									else
									{
										RelationDatabase.DownloadFamily(newDB, this, objectForAdd.dbObject, "rvt");
									}
								}
							}
							catch (Exception)
							{
							}
						}
						if (!myProgressBar.ProgressStep(1) && myProgressBar.IsStoped)
						{
							myProgressBar.Dispose();
							MessageBox.Show("中断操作！");
							return false;
						}
					}
				}
				myProgressBar.Dispose();
				result = true;
			}
			catch (Exception ex)
			{
				if (myProgressBar != null)
				{
					myProgressBar.Dispose();
				}
				throw ex;
			}
			return result;
		}

		public static void UpdateFamilyFile(RelationDatabase newDB, RelationDatabase tagDB, DbObject family, string exeName)
		{
			try
			{
				FileInfo fi = newDB.ObjectFileTable[family, exeName];
				tagDB.ObjectFileTable.Replace(family, fi);
				tagDB.ObjectTable.Update(family);
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		public static void DownloadFamily(RelationDatabase newDB, RelationDatabase tagDB, DbObject family, string exeName)
		{
			FileInfo fileInfo = newDB.ObjectFileTable[family, exeName];
			DbTransaction dbTransaction = null;
			try
			{
				DbCategory category = newDB.CategoryTable[family.ParentId];
				dbTransaction = tagDB.StartTransaction();
				tagDB.ObjectTable.Add(category, family, dbTransaction);
				tagDB.ObjectFileTable.Add(family, fileInfo, dbTransaction);
				tagDB.CommitTransaction(dbTransaction);
			}
			catch (Exception ex)
			{
				tagDB.RollbackTransaction(dbTransaction);
				throw ex;
			}
			finally
			{
				fileInfo.Delete();
				dbTransaction.Dispose();
			}
		}

		public void Compare(RelationDatabase newDb, TreeView tv)
		{
			tv.Nodes.Clear();
			List<DbCategory> all = newDb.CategoryTable.GetAll();
			DbSubject dbSubject = newDb.SubjectTable.AllSubject()[0];
			TreeNode treeNode = new TreeNode(dbSubject.ToString());
			treeNode.Name = dbSubject.Name;
			treeNode.Tag = dbSubject;
			RelationDatabase.SetCategoryNode(treeNode, all, this, newDb);
			tv.Nodes.Add(treeNode);
			tv.ExpandAll();
		}

		public static void FillTree(TreeView tree, List<RelationDatabase> dbs)
		{
			try
			{
				tree.Nodes.Clear();
				for (int i = 0; i < dbs.Count<RelationDatabase>(); i++)
				{
					RelationDatabase.DataBaseFillTree(dbs[i], tree);
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}

		private static void DataBaseFillTree(RelationDatabase db, TreeView tree)
		{
			try
			{
				List<DbCategory> all = db.CategoryTable.GetAll();
				DbSubject dbSubject = db.SubjectTable.AllSubject()[0];
				TreeNode treeNode = new TreeNode(dbSubject.ToString());
				treeNode.Name = dbSubject.Name;
				treeNode.Tag = dbSubject;
				RelationDatabase.SetChildNode(treeNode, all);
				tree.Nodes.Add(treeNode);
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}

		private static void SetChildNode(TreeNode tn, List<DbCategory> cl)
		{
			foreach (DbCategory dbCategory in cl)
			{
				if (tn.Tag is DbCategory)
				{
					if (dbCategory.ParentId == ((DbCategory)tn.Tag).Guid)
					{
						TreeNode treeNode = new TreeNode(dbCategory.ToString());
						treeNode.Name = dbCategory.Name;
						treeNode.Tag = dbCategory;
						treeNode.ImageIndex = 1;
						if (dbCategory.Limit)
						{
							treeNode.ForeColor = System.Drawing.Color.Red;
						}
						RelationDatabase.SetChildNode(treeNode, cl);
						tn.Nodes.Add(treeNode);
					}
				}
				else if (tn.Tag is DbSubject)
				{
					DbSubject dbSubject = (DbSubject)tn.Tag;
					if (dbCategory.ParentId == dbSubject.Guid)
					{
						TreeNode treeNode2 = new TreeNode(dbCategory.ToString());
						treeNode2.Name = dbCategory.Name;
						treeNode2.Tag = dbCategory;
						treeNode2.ImageIndex = 1;
						if (dbCategory.Limit)
						{
							treeNode2.ForeColor = System.Drawing.Color.Red;
						}
						RelationDatabase.SetChildNode(treeNode2, cl);
						tn.Nodes.Add(treeNode2);
					}
				}
			}
		}

		private static void SetCategoryNode(TreeNode tn, List<DbCategory> cl, RelationDatabase oldDb, RelationDatabase newDb)
		{
			foreach (DbCategory dbCategory in cl)
			{
				if (tn.Tag is CategoryForAdd)
				{
					if (dbCategory.ParentId == ((CategoryForAdd)tn.Tag).Category.Guid)
					{
						List<DbObject> second = oldDb.ObjectTable[dbCategory];
						List<DbObject> list = newDb.ObjectTable[dbCategory].Except(second).ToList<DbObject>();
						CategoryForAdd categoryForAdd = new CategoryForAdd(dbCategory);
						foreach (DbObject obj in list)
						{
							categoryForAdd.FamilyList.Add(new ObjectForAdd(obj));
						}
						TreeNode treeNode = new TreeNode(dbCategory.ToString());
						treeNode.Name = dbCategory.Name;
						treeNode.Tag = categoryForAdd;
						RelationDatabase.SetCategoryNode(treeNode, cl, oldDb, newDb);
						tn.Nodes.Add(treeNode);
					}
				}
				else if (tn.Tag is DbSubject)
				{
					DbSubject dbSubject = (DbSubject)tn.Tag;
					if (dbCategory.ParentId == dbSubject.Guid)
					{
						List<DbObject> second2 = oldDb.ObjectTable[dbCategory];
						List<DbObject> list2 = newDb.ObjectTable[dbCategory].Except(second2).ToList<DbObject>();
						CategoryForAdd categoryForAdd2 = new CategoryForAdd(dbCategory);
						foreach (DbObject obj2 in list2)
						{
							categoryForAdd2.FamilyList.Add(new ObjectForAdd(obj2));
						}
						TreeNode treeNode2 = new TreeNode(dbCategory.ToString());
						treeNode2.Name = dbCategory.Name;
						treeNode2.Tag = categoryForAdd2;
						RelationDatabase.SetCategoryNode(treeNode2, cl, oldDb, newDb);
						tn.Nodes.Add(treeNode2);
					}
				}
			}
		}

		public const string dbFolder = "FamilyLib";

		public const string dbExName = ".db";

		protected string mName = "";
	}
}
